package com.csii.config.shiro;

import com.csii.config.shiro.session.AdhocSessionFactory;
import com.csii.config.shiro.session.AdhocSessionListener;
import com.csii.config.shiro.session.ShiroSessionManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        // 创建 ShiroFilterFactoryBean 对象，用于创建 ShiroFilter 过滤器
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        // 设置 SecurityManager
        filterFactoryBean.setSecurityManager(this.securityManager());
        // 设置 URL 们
        filterFactoryBean.setLoginUrl("/login"); // 登陆 URL
       // filterFactoryBean.setSuccessUrl("/login_success"); // 登陆成功 URL
        //filterFactoryBean.setUnauthorizedUrl("/unauthorized"); // 无权限 URL
        // 设置 URL 的权限配置
        filterFactoryBean.setFilterChainDefinitionMap(this.filterChainDefinitionMap());
        return filterFactoryBean;
    }

    @Bean
    public Realm realm() {
        return new ShiroRealm();
    }

    /**
     * @return 安全管理器
     */
    @Bean("securityManager")
    public DefaultWebSecurityManager securityManager() {
        // 创建 DefaultWebSecurityManager 对象
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置其使用的 Realm
        securityManager.setRealm(this.realm());
        securityManager.setSessionManager(this.sessionManager());
        securityManager.setRememberMeManager(this.cookieRememberMeManager());
        return securityManager;
    }

    /**
     * @return 会话管理
     */
    @Bean
    public ShiroSessionManager sessionManager(){
        ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
        shiroSessionManager.setGlobalSessionTimeout(1800000);//会话时长 单位毫秒 30分钟 30*60*1000
        //shiroSessionManager.setSessionDAO();单机暂时不设置,集群部署需要设置，将session存储到redis
        shiroSessionManager.setSessionIdCookieEnabled(true);
        SimpleCookie sessionCookie = new SimpleCookie();
        sessionCookie.setHttpOnly(true);
        sessionCookie.setMaxAge(-1);
        sessionCookie.setName("adhoc_session");
        shiroSessionManager.setSessionIdCookie(sessionCookie);
        shiroSessionManager.setSessionValidationSchedulerEnabled(false);
        List<SessionListener> listeners = new ArrayList<>();
        listeners.add(new AdhocSessionListener());
        shiroSessionManager.setSessionListeners(listeners);
        shiroSessionManager.setSessionFactory(new AdhocSessionFactory());
        return shiroSessionManager;
    }

    @Bean
    public CookieRememberMeManager cookieRememberMeManager(){
        CookieRememberMeManager meManager = new CookieRememberMeManager();
        meManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdaga=="));
        SimpleCookie cookie = new SimpleCookie();
        cookie.setName("rememberMe");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(2592000);
        meManager.setCookie(cookie);
        return meManager;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public MethodInvokingFactoryBean MethodInvokingFactoryBean() {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        methodInvokingFactoryBean.setArguments(this.securityManager());
        return methodInvokingFactoryBean;
    }
    private Map<String, String> filterChainDefinitionMap() {
        Map<String, String> filterMap = new LinkedHashMap<>(); // 注意要使用有序的 LinkedHashMap ，顺序匹配
        filterMap.put("/common/login", "anon"); // 登陆接口
        //filterMap.put("/**", "authc"); // 默认剩余的 URL ，需要经过认证
        filterMap.put("/**", "anon"); // 默认剩余的 URL ，需要经过认证
        return filterMap;
    }

}
